'''
The module overrides Python select function..

@author: Hatem Oraby
'''

import select
import errno
import _socket
import os

originalSelectModule = select
originalSelectFn = select.select


def installModule():
    '''
    Overrides Python Select.select module with the new overridden
    function L{simSelect}.
    '''
    from twistedSim.overrideManager import OverrideManager
    OverrideManager.storeEntity(originalFn = originalSelectModule.select,
                                   fullName = "select.select")
    import select
    #originalSelectModule.select = simSelect
    select.select = simSelect
    
if os.name == "posix":
    try:
        _ePoll = select.epoll(1)
    except AttributeError: #check Python version, it breaks old Python
        _ePoll = select.poll()
    
def _poll(fileno,mask):
    '''
    A hack for emulating poll function. Yet to be enhanced later.
    s'''
    _ePoll.register(fileno, mask)
    events = _ePoll.poll(0)
    _ePoll.unregister(fileno)
    return events

def simSelect(r, w, e, timeout):
    '''Emulates the select.select() function.'''
    module = _socket._getCurrentModule()
    
    rSub = []
    wSub = []
    eSub = []
    
    #if platform == windows then make sure that its of socket type    
    for descriptor in r:
        if isinstance(descriptor, int):
            fileno = descriptor #just making sure that it's an integer
        elif hasattr(descriptor, 'fileno'):
            fileno = descriptor.fileno()
        else: #or should i raise???
            continue
        if module.isFileDescExists(fileno):
            skt = module.getFileDesc(fileno)
            #if type of socket not socket
                #raise originalSelect.error,(10093, 'Either the application' + 
                #        'has not called WSAStartup, or WSAStartup failed') 
                #That error is for xp
            if skt.isNewRead():# or skt.isDisconected(): 
                if fileno not in rSub:
                    rSub.append(descriptor)
        else:
            if os.name == "posix":
                #result, ignore, ignore = originalSelectFn([fileno],[],[],0)
                result = _poll(fileno, select.POLLIN)
                if result:
                    rSub.append(result[0])
            else:
                raise _socket.SocketErrors.badDescriptor
                
    #Since buffer is not implemented yet, then all are connected sockets are 
    # available for writing.
    wSub = []
    for descriptor in w:
        if isinstance(descriptor, int):
            fileno = descriptor #just making sure that it's an integer
        elif hasattr(descriptor, 'fileno'):
            fileno = descriptor.fileno()
        else:
            continue
        if module.isFileDescExists(fileno):
            obj = module.getFileDesc(fileno)
            #if type of socket not socket
                #raise originalSelect.error,(10093, 'Either the application' + 
                #        'has not called WSAStartup, or WSAStartup failed') 
            if isinstance(obj, _socket._SocketOverride):
                if obj.isNewWrite(): #and there is free buffer
                    wSub += [descriptor]
        else:
            if os.name == "posix":
                #ignore, result, ignore = originalSelectFn([],[fileno],[],0)
                result = _poll(fileno, select.POLLOUT)
                if result:
                    wSub.append(result[0])
            else:
                raise _socket.SocketErrors.badDescriptor
                     
                                                         
    #Improve this part later (rather understand it)                    
    for descriptor in e:
        if e in w:
            continue#I'll do the same thing
                    #just make sure that you its also valid for pipes.
        if isinstance(descriptor, int):
            fileno = descriptor
        elif hasattr(descriptor, 'fileno'):
            fileno = descriptor.fileno()
        else:
            continue
        
        if module.isFileDescExists(fileno):
            obj = module.getFileDesc(fileno)
            if isinstance(obj, _socket._SocketOverride):
                judge = obj.isNewWrite()
                if judge: #and there is free buffer
                    eSub += [descriptor]
        else:
            if os.name == "posix":
                #ignore, ignore, result = originalSelectFn([],[],[fileno],0)
                result = _poll(fileno, select.POLLOUT)
                if result:
                    eSub.append(result[0])
            else:
                raise _socket.SocketErrors.badDescriptor
      
    return rSub,wSub,eSub
